#include "bsp_uart.h"

/**
 * @brief  Configure serial port parameters, 8, N, 1.
 * @param  None.
 * @return None.
 * @author bagy
 * @date   2024/08/07
 * @note   Enable serial port idle interrupt, receive interrupt.
*/
static void bsp_uart_init(bsp_uart_t *uart_handle, uint32_t len)
{
    rcu_periph_clock_enable(uart_handle->rcu_clk);

    usart_deinit(uart_handle->usart_periph);

    usart_baudrate_set(uart_handle->usart_periph            , uart_handle->baudrate);
    usart_word_length_set(uart_handle->usart_periph         , uart_handle->data_len);
    usart_parity_config(uart_handle->usart_periph           , uart_handle->parity  );
    usart_stop_bit_set(uart_handle->usart_periph            , uart_handle->stop_bit);
    usart_hardware_flow_rts_config(uart_handle->usart_periph, USART_RTS_DISABLE    );
    usart_hardware_flow_cts_config(uart_handle->usart_periph, USART_CTS_DISABLE    );
    
    usart_enable(uart_handle->usart_periph);

    bsp_dma_init(&uart_handle->tx_dma, len);
    bsp_dma_init(&uart_handle->rx_dma, len);

    nvic_irq_enable(uart_handle->irq, uart_handle->pre_priority, uart_handle->sub_priority);
    nvic_irq_enable(uart_handle->tx_dma.irq, uart_handle->tx_dma.pre_priority, uart_handle->tx_dma.sub_priority);
    nvic_irq_enable(uart_handle->rx_dma.irq, uart_handle->rx_dma.pre_priority, uart_handle->rx_dma.sub_priority);

    /* 判断是否使能发送模式 */
    if(uart_handle->uart_mode & (1 << 1))
    {
        /* 使能DMA发送 */
        usart_transmit_config(uart_handle->usart_periph, USART_TRANSMIT_ENABLE);
        usart_dma_transmit_config(uart_handle->usart_periph, USART_TRANSMIT_DMA_ENABLE);
    }
    else
    {
        usart_transmit_config(uart_handle->usart_periph, USART_TRANSMIT_DISABLE);
        usart_dma_transmit_config(uart_handle->usart_periph, USART_TRANSMIT_DMA_DISABLE);     
        usart_interrupt_disable(uart_handle->usart_periph, USART_INT_TC);   
    }

    /* 判断是否使能接收模式，若使能，则开启空闲中断和DMA接收完成、使能DMA接收，默认不开启DMA半中断 */
    if(uart_handle->uart_mode & (1 << 3))
    {   
        /* 使能DMA接收 */
        dma_channel_enable(uart_handle->rx_dma.dma_periph, uart_handle->rx_dma.channel);
        usart_receive_config(uart_handle->usart_periph, USART_RECEIVE_ENABLE);
        usart_dma_receive_config(uart_handle->usart_periph, USART_RECEIVE_DMA_ENABLE);

        /* 清除空闲中断标志并使能空闲中断 */
        usart_interrupt_flag_clear(uart_handle->usart_periph, USART_INT_FLAG_IDLE);
        usart_interrupt_enable(uart_handle->usart_periph, USART_INT_IDLE);
    }
    else
    {
        dma_channel_disable(uart_handle->rx_dma.dma_periph, uart_handle->rx_dma.channel);
        usart_receive_config(uart_handle->usart_periph, USART_RECEIVE_DISABLE);
        usart_dma_receive_config(uart_handle->usart_periph, USART_RECEIVE_DMA_DISABLE);
        usart_interrupt_disable(uart_handle->usart_periph, USART_INT_IDLE);
    }
}

/**
 * @brief  串口初始化，配置DMA发送、DMA接收通道及中断优先级等.
 * @param  uart_handle 串口句柄
 * @param  buff        待发送的串口消息
 * @param  len         发送的数据长度
 * @author bagy
 * @date   2024/12/19
 */
void bsp_uart_send_buff(bsp_uart_t *uart_handle, uint8_t *buff, uint32_t len)
{
    if(uart_handle->tx_dma.tran_buff != NULL)
        memcpy((uint8_t *)uart_handle->tx_dma.tran_buff, (const uint8_t *)buff, len);    

    dma_transfer_number_config(uart_handle->tx_dma.dma_periph, uart_handle->tx_dma.channel, len);

    dma_channel_enable(uart_handle->tx_dma.dma_periph, uart_handle->tx_dma.channel);
}

/**
 * @brief  串口初始化，配置DMA发送、DMA接收通道及中断优先级等.
 * @param  uart_handle 串口句柄
 * @author bagy
 * @date   2024/12/19
 */
void bsp_uart_config(bsp_uart_t *uart_handle, uart_idle_int_cb_fn uart_idle_int_cb)
{
    ES_ASSERT(uart_handle != NULL);
    ES_ASSERT(uart_idle_int_cb != NULL);

    uart_handle->tx_dma.tran_buff = (uint8_t *)malloc(uart_handle->rec_max);
    if(uart_handle->tx_dma.tran_buff == NULL)
    {
        log_e("<%s> tx dma memory malloc failed. malloc len:%ld.\r\n", __func__, uart_handle->rec_max);
        while(1);
    }

    uart_handle->rx_dma.tran_buff = (uint8_t *)malloc(uart_handle->rec_max);
    if(uart_handle->rx_dma.tran_buff == NULL)
    {
        log_e("<%s> rx dma memory malloc failed. malloc len:%ld.\r\n", __func__, uart_handle->rec_max);
        while(1);
    }

    bsp_gpio_config(&uart_handle->tx_pin, ALT_FUN_EN);
    bsp_gpio_config(&uart_handle->rx_pin, ALT_FUN_EN);

    bsp_uart_init(uart_handle, uart_handle->rec_max);

    uart_handle->uart_idle_int_cb = uart_idle_int_cb;
}
